﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using InHD.model;
using System.Data;
using System.Reflection;
using InHD.utilities;

namespace InHD.dataaccess
{
    class ProductRepository
    {
        #region Fields

        List<Product> _products;
        private List<string> _selectedCategories;
        private Dictionary<string, List<Product>> _productsByCategory;
//For DB Utils
        private DBUltils _db;
        string[] _paramName;
        string[] _value;
        DBUltils.ParamType[] _paramType;
        #endregion // Fields

        #region Constructor

        /// <summary>
        /// Creates a new repository of CompanyInfos.
        /// </summary>
        public ProductRepository()
        {
            _products = new List<Product>();
            this._selectedCategories = new List<string>();
            this._productsByCategory = new Dictionary<string, List<Product>>();
            this._db = new DBUltils();
            if (!_db.connectDB(Constants.Security.DefaultDBUser, Constants.Security.DefaultDBPassword))
                throw new ArgumentNullException(Constants.Messages.CannotConnectDB);
        }

        #endregion // Constructor

        #region Public Interface

        public event EventHandler<ProductAddedEventArgs> ProductAdded;

        public string AddProduct(Product product)
        {
            try
            {
                if (product == null)
                    throw new ArgumentNullException("product");
                for (int i = 0; i < this._products.Count; i++)
                {
                    if (this._products[i].SerialNo.Equals(product.SerialNo))
                    {
                        return "DuplicateCode";
                    }
                }
                //product.SerialNo = Guid.NewGuid().ToString();
                //// Add new product into database
                if (_db == null)
                    throw new ArgumentNullException(Constants.Messages.DBNotInitialized);
                if ((product.ProductUNK == null) || (product.CategoryUNK == null) || (product.SupplierUNK == null))
                    throw new ArgumentNullException("Null UNK");
                if (product.Description == null)
                    product.Description = string.Empty;
                _paramName = new string[]{"@productUNK",
                                        "@proDes",
                                        "@quantity",
                                        "@retailPrc",
                                        "@salePrc",
                                        "@importPrice",
                                        "@proName",
                                        "@categoryUNK",
                                        "@categoryName",
                                        "@sn",
                                        "@supplierUNK",
                                        "@lastAccess",};
                _paramType = new DBUltils.ParamType[]{DBUltils.ParamType.Str,
                                                    DBUltils.ParamType.LNStr,
                                                    DBUltils.ParamType.Int,
                                                    DBUltils.ParamType.Real,
                                                    DBUltils.ParamType.Real,
                                                    DBUltils.ParamType.Real,
                                                    DBUltils.ParamType.NStr,
                                                    DBUltils.ParamType.Str,
                                                    DBUltils.ParamType.NStr,
                                                    DBUltils.ParamType.Str,
                                                    DBUltils.ParamType.Str,
                                                    DBUltils.ParamType.DateTime
                                                    };
                _value = new string[]{product.ProductUNK,
                                  product.Description,
                                  product.Quantity.ToString(),
                                  product.RetailPrice.ToString(),
                                  product.WholesalePrice.ToString(),
                                  product.ImportPrice.ToString(),
                                  product.Name,
                                  product.CategoryUNK,
                                  product.CategoryName,
                                  product.SerialNo,
                                  product.SupplierUNK,
                                  DateTime.Now.ToString()
                                    };

                _db.queryDB(Constants.StoreProcedures.Product.AddProduct, _paramName, _paramType, _value, DBUltils.QueryType.Insert);
                _products.Add(product);

                if (this.KeyExistingInDict(product.CategoryUNK))
                {
                    this._productsByCategory[product.CategoryUNK].Add(product);
                }
                else
                {
                    this._productsByCategory.Add(product.CategoryUNK, new List<Product>() { product });
                }

                if (this.ProductAdded != null)
                    this.ProductAdded(this, new ProductAddedEventArgs(product));
            }
            catch (Exception e)
            {
                Logger.RecordMessage(e, MessageType.Error);
                return e.Message;
            }

            return string.Empty;
        }

        public string EditProduct(Product product)
        {
            try
            {
                if (product == null)
                    throw new ArgumentNullException("product");

                //// edit existing product which have productUNK  == product.ProductUNK
                for (int i = 0; i < this._products.Count; i++)
                {
                    if (this._products[i].ProductUNK.Equals(product.ProductUNK))
                    {
                        for (int j = 0; j < this._products.Count; j++)
                        {
                            if ((i != j) && this._products[j].SerialNo.Equals(product.SerialNo))
                            {
                                return "DuplicateCode";
                            }
                        }
                        this._products[i] = product;
                        if (_db == null)
                            throw new ArgumentNullException(Constants.Messages.DBNotInitialized);
                        if (product.Description == null)
                            product.Description = string.Empty;
                        _paramName = new string[]{"@productUNK",
                                        "@proDes",
                                        "@quantity",
                                        "@retailPrc",
                                        "@salePrc",
                                        "@importPrice",
                                        "@proName",
                                        "@categoryUNK",
                                        "@categoryName",
                                        "@sn",
                                        "@supplierUNK",
                                        "@lastAccess",};
                        _paramType = new DBUltils.ParamType[]{DBUltils.ParamType.Str,
                                                    DBUltils.ParamType.LNStr,
                                                    DBUltils.ParamType.Int,
                                                    DBUltils.ParamType.Real,
                                                    DBUltils.ParamType.Real,
                                                    DBUltils.ParamType.Real,
                                                    DBUltils.ParamType.NStr,
                                                    DBUltils.ParamType.Str,
                                                    DBUltils.ParamType.NStr,
                                                    DBUltils.ParamType.Str,
                                                    DBUltils.ParamType.Str,
                                                    DBUltils.ParamType.DateTime
                                                    };
                        _value = new string[]{product.ProductUNK,
                                  product.Description,
                                  product.Quantity.ToString(),
                                  product.RetailPrice.ToString(),
                                  product.WholesalePrice.ToString(),
                                  product.ImportPrice.ToString(),
                                  product.Name,
                                  product.CategoryUNK,
                                  product.CategoryName,
                                  product.SerialNo,
                                  product.SupplierUNK,
                                  DateTime.Now.ToString()
                                    };

                        _db.queryDB(Constants.StoreProcedures.Product.UpdateProduct, _paramName, _paramType, _value, DBUltils.QueryType.Update);
                        break;
                    }
                }

                for (int i = 0; i < this._productsByCategory[product.CategoryUNK].Count; i++)
                {
                    Product p = this._productsByCategory[product.CategoryUNK][i];
                    if (p.ProductUNK.Equals(product.ProductUNK))
                    {
                        p = product;
                        
                    }
                }
                
                return string.Empty;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        public string DeleteProduct(string UNK)
        {
            bool found = false;
            foreach (Product product in this._products)
            {
                if (product.ProductUNK.Equals(UNK))
                {
                    this._products.Remove(product);
                    found = true;
                    break;
                }
            }
            if (!found)
                return "UNK is not exist";
            try
            {
                if (_db == null)
                    throw new ArgumentNullException(Constants.Messages.DBNotInitialized);
                if (UNK == null)
                    throw new ArgumentNullException("Null Unique key");
                _paramName = new string[] { "@productUNK" };
                _paramType = new DBUltils.ParamType[] { DBUltils.ParamType.Str };
                _value = new string[] { UNK };

                _db.queryDB(Constants.StoreProcedures.Product.DeleteProduct, _paramName, _paramType, _value, DBUltils.QueryType.Delete);
            }
            catch (Exception e)
            {
                Logger.RecordMessage(e, MessageType.Error);
                return e.Message;
            }
            
            return string.Empty;
        }

        public List<Product> GetProducts(string categoryUNK)
        {
            return string.IsNullOrEmpty(categoryUNK) ? this._products : this._productsByCategory[categoryUNK];
        }

        private bool KeyExistingInDict(string key)
        {
            foreach (string str in this._productsByCategory.Keys)
            {
                if (str.Equals(key))
                {
                    return true;
                }
            }

            return false;
        }

        public string LoadProductBySupplierAndCategory(string supplierUnk, string categoryUNK)
        {
            try
            {
                //// Load from database a datatable of products with inputed categoryUNK
                if (_db == null)
                    throw new ArgumentNullException(Constants.Messages.DBNotInitialized);
                DataSet ds;
                if (categoryUNK == "")
                {
                    _paramName = new string[] { "@supplierUNK" };
                    _paramType = new DBUltils.ParamType[] { DBUltils.ParamType.Str };
                    _value = new string[] { supplierUnk };
                    ds = _db.queryDB("GetProductsOfSupplier", _paramName, _paramType, _value, DBUltils.QueryType.Select);
                }
                else
                {
                    _paramName = new string[] { "@supplierUNK", "@categoryUNK" };
                    _paramType = new DBUltils.ParamType[] { DBUltils.ParamType.Str, DBUltils.ParamType.Str };
                    _value = new string[] { supplierUnk, categoryUNK };
                    ds = _db.queryDB("GetProductBySupplierAndCategory", _paramName, _paramType, _value, DBUltils.QueryType.Select);
                }
                // DUMMIE
                DataTable dt = new DataTable();
                dt.Columns.Add("Description");
                dt.Columns.Add("Name");
                dt.Columns.Add("Quantity");
                dt.Columns.Add("RetailPrice");
                dt.Columns.Add("WholesalePrice");
                dt.Columns.Add("CategoryUNK");
                dt.Columns.Add("CategoryName");
                dt.Columns.Add("SerialNo");
                dt.Columns.Add("SupplierUNK");
                dt.Columns.Add("ProductUNK");
                dt.Columns.Add("LastAccess");
                dt.Columns.Add("ImportPrice");

                for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                {
                    DataRow row = dt.NewRow();
                    row["Description"] = ds.Tables[0].Rows[i]["proDescription"].ToString();
                    row["Name"] = ds.Tables[0].Rows[i]["proName"].ToString();
                    row["Quantity"] = ds.Tables[0].Rows[i]["quantityOnStore"].ToString();
                    row["RetailPrice"] = ds.Tables[0].Rows[i]["retailUnitPrice"].ToString();
                    row["WholesalePrice"] = ds.Tables[0].Rows[i]["wholesaleUnitPrice"].ToString();
                    row["CategoryUNK"] = ds.Tables[0].Rows[i]["categoryUNK"].ToString();
                    row["CategoryName"] = ds.Tables[0].Rows[i]["categoryName"].ToString();
                    row["SerialNo"] = ds.Tables[0].Rows[i]["sn"].ToString();
                    row["SupplierUNK"] = ds.Tables[0].Rows[i]["supplierUNK"].ToString();
                    row["ProductUNK"] = ds.Tables[0].Rows[i]["productUNK"].ToString();
                    row["LastAccess"] = ds.Tables[0].Rows[i]["lastAccess"].ToString();
                    row["ImportPrice"] = ds.Tables[0].Rows[i]["importPrice"].ToString();

                    dt.Rows.Add(row);
                    dt.AcceptChanges();
                }
                //--------
                _products = new List<Product>();
                foreach (DataRow r in dt.Rows)
                {
                    _products.Add(Product.CreateProductInfo(
                        Convert.ToString(r["Description"]),
                        Convert.ToString(r["Name"]),
                        Convert.ToInt32(r["Quantity"]),
                        Convert.ToDouble(r["RetailPrice"]),
                        Convert.ToDouble(r["WholesalePrice"]),
                        Convert.ToString(r["CategoryUNK"]),
                        Convert.ToString(r["CategoryName"]),
                        Convert.ToString(r["SerialNo"]),
                        Convert.ToString(r["SupplierUNK"]),
                        Convert.ToString(r["ProductUNK"]),
                        Convert.ToDateTime(r["LastAccess"]),
                        Convert.ToDouble(r["ImportPrice"])));
                }

                if (!string.IsNullOrEmpty(categoryUNK))
                {
                    if (this.KeyExistingInDict(categoryUNK))
                    {
                        this._productsByCategory[categoryUNK] = _products;
                    }
                    else
                    {
                        this._productsByCategory.Add(categoryUNK, _products);
                    }
                }

            }
            catch (Exception e)
            {
                Logger.RecordMessage(e, MessageType.Error);
                return e.Message;
            }
            return string.Empty;
        }

        public string LoadProductsByCategory(string categoryUNK)
        {
            try
            {
                if (this.WasNotSelected(categoryUNK))
                {
                    this._selectedCategories.Add(categoryUNK);

                    //// Load from database a datatable of products with inputed categoryUNK
                    if (_db == null)
                        throw new ArgumentNullException(Constants.Messages.DBNotInitialized);
                    DataSet ds;
                    if (categoryUNK == "")
                        ds = _db.queryDB("GetAllProductByCategory", _paramName, _paramType, _value, DBUltils.QueryType.Select);
                    else
                    {
                        _paramName = new string[1];
                        _paramType = new DBUltils.ParamType[1];
                        _value = new string[1];
                        _paramName[0] = "@categoryUNK";
                        _value[0] = categoryUNK; //// dummi
                        _paramType[0] = DBUltils.ParamType.Str;
                        ds = _db.queryDB("GetProductByCategory", _paramName, _paramType, _value, DBUltils.QueryType.Select);
                    }
                    // DUMMIE
                    DataTable dt = new DataTable();
                    dt.Columns.Add("Description");
                    dt.Columns.Add("Name");
                    dt.Columns.Add("Quantity");
                    dt.Columns.Add("RetailPrice");
                    dt.Columns.Add("WholesalePrice");
                    dt.Columns.Add("CategoryUNK");
                    dt.Columns.Add("CategoryName");
                    dt.Columns.Add("SerialNo");
                    dt.Columns.Add("SupplierUNK");
                    dt.Columns.Add("ProductUNK");
                    dt.Columns.Add("LastAccess");
                    dt.Columns.Add("ImportPrice");

                    for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                    {
                        DataRow row = dt.NewRow();
                        row["Description"] = ds.Tables[0].Rows[i]["proDescription"].ToString();
                        row["Name"] = ds.Tables[0].Rows[i]["proName"].ToString();
                        row["Quantity"] = ds.Tables[0].Rows[i]["quantityOnStore"].ToString();
                        row["RetailPrice"] = ds.Tables[0].Rows[i]["retailUnitPrice"].ToString();
                        row["WholesalePrice"] = ds.Tables[0].Rows[i]["wholesaleUnitPrice"].ToString();
                        row["CategoryUNK"] = ds.Tables[0].Rows[i]["categoryUNK"].ToString();
                        row["CategoryName"] = ds.Tables[0].Rows[i]["categoryName"].ToString();
                        row["SerialNo"] = ds.Tables[0].Rows[i]["sn"].ToString();
                        row["SupplierUNK"] = ds.Tables[0].Rows[i]["supplierUNK"].ToString();
                        row["ProductUNK"] = ds.Tables[0].Rows[i]["productUNK"].ToString();
                        row["LastAccess"] = ds.Tables[0].Rows[i]["lastAccess"].ToString();
                        row["ImportPrice"] = ds.Tables[0].Rows[i]["importPrice"].ToString();

                        dt.Rows.Add(row);
                        dt.AcceptChanges();
                    }
                    //--------
                    List<Product> tmpList = new List<Product>();
                    foreach (DataRow r in dt.Rows)
                    {
                        tmpList.Add(Product.CreateProductInfo(
                            Convert.ToString(r["Description"]),
                            Convert.ToString(r["Name"]),
                            Convert.ToInt32(r["Quantity"]),
                            Convert.ToDouble(r["RetailPrice"]),
                            Convert.ToDouble(r["WholesalePrice"]),
                            Convert.ToString(r["CategoryUNK"]),
                            Convert.ToString(r["CategoryName"]),
                            Convert.ToString(r["SerialNo"]),
                            Convert.ToString(r["SupplierUNK"]),
                            Convert.ToString(r["ProductUNK"]),
                            Convert.ToDateTime(r["LastAccess"]),
                            Convert.ToDouble(r["ImportPrice"])));
                    }

                    if (!string.IsNullOrEmpty(categoryUNK))
                    {
                        if (this.KeyExistingInDict(categoryUNK))
                        {
                            foreach (Product p in tmpList)
                            {
                                this._productsByCategory[categoryUNK].Add(p);
                            }
                        }
                        else
                        {
                            this._productsByCategory.Add(categoryUNK, tmpList);
                        }
                    }

                    foreach (Product p in tmpList)
                    {
                        this._products.Add(p);
                    }
                }
            }
            catch (Exception e)
            {
                Logger.RecordMessage(e, MessageType.Error);
                return e.Message;
            }
            return string.Empty;
        }

        public string LoadProductBySupplier(string supUNK)
        {
            try
            {
                DataSet ds;
                if (supUNK == "")
                    ds = _db.queryDB("GetAllProductBySupplierEx", _paramName, _paramType, _value, DBUltils.QueryType.Select);
                else
                {
                    _paramName = new string[] { "@supplierUNK" };
                    _paramType = new DBUltils.ParamType[] { DBUltils.ParamType.Str };
                    _value = new string[] { supUNK };

                    ds = _db.queryDB("GetProductBySupplierEx", _paramName, _paramType, _value, DBUltils.QueryType.Select);
                }
                DataTable dt = new DataTable();
                dt.Columns.Add("Description");
                dt.Columns.Add("Name");
                dt.Columns.Add("Quantity");
                dt.Columns.Add("ImportPrice");
                dt.Columns.Add("CategoryUNK");
                dt.Columns.Add("CategoryName");
                dt.Columns.Add("SerialNo");
                dt.Columns.Add("SupplierUNK");
                dt.Columns.Add("ProductUNK");
                dt.Columns.Add("LastAccess");
                dt.Columns.Add("ImportPrice");

                for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                {
                    DataRow row = dt.NewRow();
                    row["Description"] = ds.Tables[0].Rows[i]["proDescription"].ToString();
                    row["Name"] = ds.Tables[0].Rows[i]["proName"].ToString();
                    row["Quantity"] = ds.Tables[0].Rows[i]["quantityOnStore"].ToString();
                    row["ImportPrice"] = ds.Tables[0].Rows[i]["importPrice"].ToString();
                    row["CategoryUNK"] = ds.Tables[0].Rows[i]["categoryUNK"].ToString();
                    row["SerialNo"] = ds.Tables[0].Rows[i]["sn"].ToString();
                    row["SupplierUNK"] = ds.Tables[0].Rows[i]["supplierUNK"].ToString();
                    row["ProductUNK"] = ds.Tables[0].Rows[i]["productUNK"].ToString();
                    row["LastAccess"] = ds.Tables[0].Rows[i]["lastAccess"].ToString();
                    row["ImportPrice"] = ds.Tables[0].Rows[i]["importPrice"].ToString();

                    dt.Rows.Add(row);
                    dt.AcceptChanges();
                }
                //--------
                List<Product> tmpList = new List<Product>();
                foreach (DataRow r in dt.Rows)
                {
                    tmpList.Add(Product.CreateProductInfo(
                        Convert.ToString(r["Description"]),
                        Convert.ToString(r["Name"]),
                        Convert.ToInt32(r["Quantity"]),
                        Convert.ToDouble(r["RetailPrice"]),
                        Convert.ToDouble(r["WholesalePrice"]),
                        Convert.ToString(r["CategoryUNK"]),
                        Convert.ToString(r["CategoryName"]),
                        Convert.ToString(r["SerialNo"]),
                        Convert.ToString(r["SupplierUNK"]),
                        Convert.ToString(r["ProductUNK"]),
                        Convert.ToDateTime(r["LastAccess"]),
                        Convert.ToDouble(r["ImportPrice"])));
                }

                if (!string.IsNullOrEmpty(supUNK))
                {
                    if (this.KeyExistingInDict(supUNK))
                    {
                        foreach (Product p in tmpList)
                        {
                            this._productsByCategory[supUNK].Add(p);
                        }
                    }
                    else
                    {
                        this._productsByCategory.Add(supUNK, tmpList);
                    }
                }

                foreach (Product p in tmpList)
                {
                    this._products.Add(p);
                }
            }
            catch (Exception e)
            {
                Logger.RecordMessage(e, MessageType.Error);
                return e.Message;
            }
            return string.Empty;
        }

        public string SearchProduct(string startingText)
        {
            try
            {
                this._products.Clear();
                if (_db == null)
                    throw new ArgumentNullException(Constants.Messages.DBNotInitialized);
                DataSet ds;
                _paramName = new string[1];
                _paramType = new DBUltils.ParamType[1];
                _value = new string[1];
                _paramName[0] = "@textSearch";
                _value[0] = startingText; //// dummi
                _paramType[0] = DBUltils.ParamType.Str;
                ds = _db.queryDB("SearchProduct", _paramName, _paramType, _value, DBUltils.QueryType.Select);
                if (ds != null && ds.Tables[0] != null && ds.Tables[0].Rows.Count != 0)
                {
                    List<Product> tmpList = new List<Product>();
                    foreach (DataRow r in ds.Tables[0].Rows)
                    {
                        tmpList.Add(Product.CreateProductInfo(
                            Convert.ToString(r["proDescription"]),
                            Convert.ToString(r["proName"]),
                            Convert.ToInt32(r["quantityOnStore"]),
                            Convert.ToDouble(r["retailUnitPrice"]),
                            Convert.ToDouble(r["wholesaleUnitPrice"]),
                            Convert.ToString(r["categoryUNK"]),
                            Convert.ToString(r["categoryName"]),
                            Convert.ToString(r["sn"]),
                            Convert.ToString(r["supplierUNK"]),
                            Convert.ToString(r["productUNK"]),
                            Convert.ToDateTime(r["lastAccess"]),
                            Convert.ToDouble(r["importPrice"])));
                    }

                    foreach (Product p in tmpList)
                    {
                        this._products.Add(p);
                    }
                }
            }
            catch (Exception e)
            {
                Logger.RecordMessage(e, MessageType.Error);
                return e.Message;
            }
            return string.Empty;
        }

        private bool WasNotSelected(string categoryUNK)
        {
            foreach (string tmpStr in this._selectedCategories)
            {
                if (tmpStr.Equals(categoryUNK))
                {
                    return false;
                }
            }

            return true;
        }

        public Product GetProductBySerialNo(string serial)
        {
            return Product.CreateProduct();
        }

        public List<Product> GetProductsWthSearchCriteria(string categoryUNK, string property, string criteria)
        {
            if (!string.IsNullOrEmpty(categoryUNK))
            {
                return this.FindProducts(this._productsByCategory[categoryUNK], property, criteria);
            }
            else
            {
                return this.FindProducts(this._products, property, criteria);
            }
        }

        public string ReceiveProduct(string productUnk, int quantity, double importPrice)
        {
            try
            {
                if (_db == null)
                    throw new ArgumentNullException(Constants.Messages.DBNotInitialized);
                if (productUnk == null || quantity == 0)
                    throw new ArgumentNullException("productUnk == null || quantity == 0");
                _paramName = new string[]{"@productUNK",
                                        "@quantity",
                                        "@importPrice"};
                _paramType = new DBUltils.ParamType[]{DBUltils.ParamType.Str,
                                                    DBUltils.ParamType.Int,
                                                    DBUltils.ParamType.Real};
                _value = new string[]{productUnk,
                                  quantity.ToString(),
                                  importPrice.ToString()};

                _db.queryDB("ReceiveProduct", _paramName, _paramType, _value, DBUltils.QueryType.Update);
            }
            catch (Exception e)
            {
                Logger.RecordMessage(e, MessageType.Error);
                return e.Message;
            }
            return string.Empty;
        }

        public DataTable GetProductByRange(int start, int range)
        {
            DataSet ds;
            DataTable dt = new DataTable();
            if (_db == null)
                return dt;
            _paramName = new string[]{"@start", "@range"};
            _paramType = new DBUltils.ParamType[] { DBUltils.ParamType.Int, DBUltils.ParamType.Int };
            _value = new string[]{start.ToString(), range.ToString()};

            ds = _db.queryDB("GetAllProductInRange", _paramName, _paramType, _value, DBUltils.QueryType.Update);
            return ds.Tables[0];
        }

        #endregion // Public Interface

        #region Private Helpers
        
        private List<Product> FindProducts(List<Product> list, string property, string criteria)
        {
            List<Product> tmpList = new List<Product>();
            foreach (Product pro in list)
            {
                Type t = pro.GetType();
                PropertyInfo p = t.GetProperty(property);
                string valueOfProperty = Convert.ToString(p.GetValue(pro, null));
                if (valueOfProperty.ToUpper().Contains(string.IsNullOrEmpty(criteria) ? string.Empty : criteria.ToUpper()))
                {
                    tmpList.Add(pro);
                }
            }

            return tmpList;
        }
        #endregion // Private Helpers

        internal List<Product> GetLoadedProducts()
        {
            return this._products;
        }
    }
}
